home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BCI NET
/
BCI NET Dec 94.iso
/
archives
/
programming
/
source
/
tsm23s.lha
/
OpalLoad.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-08
|
37KB
|
1,202 lines
// TSMorph - Amiga Morphing program
// Copyright (C) © 1993 Topicsave Limited
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// mpaddock@cix.compulink.co.uk
// $Author: M_J_Paddock $
// $Date: 1992/08/08 01:09:24 $
// $Revision: 1.5 $
// Include precompiled headers if required
#ifndef TSMORPH_H
#include "TSMorph.h"
#endif
#include "JPEG_LS/jinclude.h"
extern UWORD FileFormat = 0; // Format of file being loaded
/* Loads an image (in various formats)
* pic : pointer to Picture structure
* filename: filename to load
* Returns : TRUE if loaded OK
*/
BOOL
MyLoadBrush (struct Picture *pic,UBYTE *filename) {
BOOL OpenILBM = FALSE; // Are we loading a (<24 plane) ILBM
char *e = NULL; // First
char *e1 = NULL; // and second part of error message
long hnum; // Help number
long err; // Error flag
BPTR fh; // File handle
UBYTE buffer[5]="\0\0\0\0"; // First 4 bytes of file for identification
// Try and open file and read 1st 4 bytes
if (fh = Open(filename,MODE_OLDFILE)) {
FRead(fh,buffer,4,1);
// check if a sort of IFF file
if (!strcmp(buffer,"LIST") ||
!strcmp(buffer,"CAT ") ||
!strcmp(buffer,"FORM")) {
FileFormat = FORMAT_IFF;
}
else {
// check if a JFIF JPEG
if ((buffer[0] == 0xFF) &&
(buffer[1] == 0xD8)) {
FileFormat = FORMAT_JPEG;
}
else {
// check if a GIF
if ((buffer[0] == 'G') &&
(buffer[1] == 'I') &&
(buffer[2] == 'F')) {
FileFormat = FORMAT_GIF;
}
else {
// check if a PPM
if ((buffer[0] == 'P') &&
((buffer[1] == '2') ||
(buffer[1] == '3') ||
(buffer[1] == '5') ||
(buffer[1] == '6'))) {
FileFormat = FORMAT_PPM;
}
else {
// Otherwise default to TARGA (the only other format we load)
FileFormat = FORMAT_TARGA;
}
}
}
}
Close(fh);
}
else {
// error file not found
FileFormat = 0;
e = "File does not exist '%s'";
hnum = HE_NoFile;
e1 = filename;
}
// If the file is and IFF and we only open ILBMs in some cases then perform some checks
if ((FileFormat == FORMAT_IFF) && ((OpenMode == OPEN_ILBM_IF_ILBM) || (OpenMode == OPEN_ILBM_IF_COLOURS))) {
if (pic->ilbm->ParseInfo.iff = AllocIFF()) {
err = queryilbm(pic->ilbm,filename);
if (!err) {
if (OpenMode == OPEN_ILBM_IF_COLOURS) {
// if we only open if screen colours then check depth
if (!(pic->ilbm->Bmhd.nPlanes > TSMorphWnd->WScreen->BitMap.Depth)) {
OpenILBM = TRUE;
}
}
else { // OpenMode == OPEN_ILBM_IF_ILBM
// if open if an ILBM then check < 24 bits
if (pic->ilbm->Bmhd.nPlanes < 24) {
OpenILBM = TRUE;
}
}
}
FreeIFF(pic->ilbm->ParseInfo.iff);
pic->ilbm->ParseInfo.iff = NULL;
}
else {
e = "Unable to AllocIFF";
hnum = HE_AllocIFF;
}
}
// If we always open ILBM or the above checks out OK then try and open
if (OpenILBM || ((OpenMode == OPEN_ILBM_ALWAYS) && !e)) {
if (pic->ilbm->ParseInfo.iff = AllocIFF()) {
// set up IFF stuff and load image
pic->ilbm->ParseInfo.propchks = props;
pic->ilbm->ParseInfo.collectchks = nowt;
pic->ilbm->ParseInfo.stopchks = stops;
if (loadbrush(pic->ilbm,filename)) {
closeifile(&(pic->ilbm->ParseInfo));
e = "Failure loading Image '%s'";
e1 = filename;
hnum = HE_LoadImage;
}
else {
closeifile(&(pic->ilbm->ParseInfo));
FreeIFF(pic->ilbm->ParseInfo.iff);
pic->ilbm->ParseInfo.iff = NULL;
return TRUE;
}
}
else {
e = "Unable to AllocIFF";
hnum = HE_AllocIFF;
}
}
else {
// otherwise try and load using another format
if (!e) {
return OpalLoad(pic,filename);
}
}
Error(e,"OK",e1,hnum);
return FALSE;
}
/* Loads an image (in various formats)
* pic : pointer to Picture structure
* filename: filename to load
* Returns : TRUE if loaded OK
*/
BOOL OpalLoad(struct Picture *pic,UBYTE *filename) {
char *e = NULL; // Error message main text
char *e1 = NULL; // sub text,
long Err; // OpalError
ULONG hnum; // Help on error
struct OpalScreen *OScrn; // OpalScreen
UBYTE *p[3]= {NULL,NULL,NULL}; // rbg planes
UBYTE r[256],g[256],b[256]; // rgb colors of screen (8 bit)
UWORD i; // loop counter
UWORD color; // Colour
UBYTE *red,*green,*blue; // rgb pointers
UWORD maxcol; // Number of colors
UWORD xadd; // bytes to add to get to next line
decompress_info_ptr info; // Load JPEG stuff
BOOL ReMap = FALSE; // Have to remap ourselves
struct RastPort Rp; // Rast port for conversion
struct DCTVCvtHandle *handle=NULL; // DCTV conversion stuff
UWORD *DCTVcolors=NULL; // DCTV palette
OpenProgressWindow(); // Open the progress window
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Creating Colormap",
TAG_END);
HandleProgressIDCMP();
}
// Store and set up to 256 colours
maxcol = min((1 << TSMorphWnd->WScreen->BitMap.Depth),256);
for (i=0; i < maxcol; ++i) {
color = GetRGB4(TSMorphWnd->WScreen->ViewPort.ColorMap,i);
r[i]=((color&0x0f00)>>4)|((color&0x0f00)>>8);
g[i]=(color&0x00f0)|((color&0x00f0)>>4);
b[i]=((color&0x000f)<<4)|(color&0x000f);
}
// If we are not opening OPAL and the file is IFF
if ((OpenMode != OPEN_OPAL) &&
(FileFormat == FORMAT_IFF)) {
// try and load IFF
if (pic->ilbm->ParseInfo.iff = AllocIFF()) {
pic->ilbm->ParseInfo.propchks = props;
pic->ilbm->ParseInfo.collectchks = nowt;
pic->ilbm->ParseInfo.stopchks = stops;
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Loading ILBM",
TAG_END);
HandleProgressIDCMP();
}
if (loadbrush(pic->ilbm,filename)) {
closeifile(&(pic->ilbm->ParseInfo));
e = "Failure loading Image '%s'";
e1 = filename;
hnum = HE_LoadImage;
}
else {
closeifile(&(pic->ilbm->ParseInfo));
if (pic->ilbm->Bmhd.nPlanes == 24) {
// 24 bit image - free colours
freecolors(pic->ilbm);
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Converting 24 bit to Chunky",
TAG_END);
HandleProgressIDCMP();
}
// Allocate Chunky planes
if ((p[0] = AllocVec(((((pic->ilbm->Bmhd.w+15)>>4)<<4)*pic->ilbm->Bmhd.h),0)) &&
(p[1] = AllocVec(((((pic->ilbm->Bmhd.w+15)>>4)<<4)*pic->ilbm->Bmhd.h),0)) &&
(p[2] = AllocVec(((((pic->ilbm->Bmhd.w+15)>>4)<<4)*pic->ilbm->Bmhd.h),0))) {
// Convert to chunky RGB
if (InitArray(pic->ilbm->Bmhd.w) && PlanarToChunky(pic,pic->ilbm->Bmhd.w,pic->ilbm->Bmhd.h,p[0],p[1],p[2])) {
// Bytes to add to get to next row
xadd = (((pic->ilbm->Bmhd.w+15)>>4)<<4) - pic->ilbm->Bmhd.w;
red = p[0];
blue = p[2];
green = p[1];
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Remapping 24 bit palette",
TAG_END);
GT_SetGadgetAttrs(ProgressGadgets[GDX_Pass2],ProgressWnd,NULL,
GTSL_Level,0,
GTSL_Max,pic->ilbm->Bmhd.h-1,TAG_END);
HandleProgressIDCMP();
}
// Convert to screen palette using 020 if present
if (((struct ExecBase *)SysBase)->AttnFlags & AFF_68020) {
RGBToScreen020(red,green,blue,pic->ilbm->Bmhd.h,pic->ilbm->Bmhd.w,maxcol,xadd,r,g,b);
}
else {
RGBToScreen000(red,green,blue,pic->ilbm->Bmhd.h,pic->ilbm->Bmhd.w,maxcol,xadd,r,g,b);
}
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Converting 24 bit to Planar",
TAG_END);
HandleProgressIDCMP();
}
// Convert back to planar
if (ChunkyToPlanar(pic,pic->ilbm->Bmhd.w,pic->ilbm->Bmhd.h,p[0])) {
// Free everything and return ok
FreeArray();
FreeVec(p[0]);
FreeVec(p[1]);
FreeVec(p[2]);
CloseProgressWindow();
return TRUE;
}
// Free everything
else {
e = "Unable to allocate memory for bitmap";
hnum = HE_AllocPlanes;
}
}
else {
e = "Unable to allocate memory for bitmap";
hnum = HE_AllocPlanes;
}
FreeArray();
}
else {
e = "Unable to allocate memory for bitmap";
hnum = HE_AllocPlanes;
}
if (p[0]) FreeVec(p[0]);
if (p[1]) FreeVec(p[1]);
if (p[2]) FreeVec(p[2]);
}
else {
// not a 24 bit image
// If we have dctv.library then check if a DCTV image
if (DCTVBase && TestDCTVSignature(pic->ilbm->brbitmap)) {
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Converting DCTV to Chunky",
TAG_END);
HandleProgressIDCMP();
}
// Allocate and set up DCTV palette
if (DCTVcolors = AllocVec(2L<<pic->ilbm->Bmhd.nPlanes,NULL)) {
for (i=0; i < (1L<<pic->ilbm->Bmhd.nPlanes); ++i) {
DCTVcolors[i] = ((pic->ilbm->RGB[i*4+1] & 0xf0) << 4) |
((pic->ilbm->RGB[i*4+2] & 0xf0)) |
((pic->ilbm->RGB[i*4+3] & 0xf0) >> 4);
}
// Allocate RGB chunky planes and DCTV stuff
if ((p[0] = AllocVec(((((pic->ilbm->Bmhd.w+15)>>4)<<4)*pic->ilbm->Bmhd.h),0)) &&
(p[1] = AllocVec(((((pic->ilbm->Bmhd.w+15)>>4)<<4)*pic->ilbm->Bmhd.h),0)) &&
(p[2] = AllocVec(((((pic->ilbm->Bmhd.w+15)>>4)<<4)*pic->ilbm->Bmhd.h),0)) &&
(InitArray(pic->ilbm->Bmhd.w)) &&
(handle = AllocDCTVCvtTags(pic->ilbm->brbitmap,
DCTVCVTA_Type, DCTVCVTT_DCTVtoRGB,
DCTVCVTA_Width, (((pic->ilbm->Bmhd.w+15)>>4)<<4),
DCTVCVTA_Height, pic->ilbm->Bmhd.h,
DCTVCVTA_Flags, ((pic->ilbm->camg & LACE)?DCTVCVTF_Lace:0)|
DCTVCVTF_CustomRGBBuf,
DCTVCVTA_ColorTable, DCTVcolors,
TAG_END))) {
handle->Red = p[0];
handle->Green = p[1];
handle->Blue = p[2];
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Pass2],ProgressWnd,NULL,
GTSL_Level,0,
GTSL_Max,pic->ilbm->Bmhd.h-1,TAG_END);
GT_SetGadgetAttrs(ProgressGadgets[GDX_Pass1],ProgressWnd,NULL,
GTSL_Level,1,
GTSL_Max,2,TAG_END);
HandleProgressIDCMP();
}
// use dctv.library to convert to chunky
while (handle->DstLineNum < handle->Height) {
CvtDCTVLine(handle);
if ((handle->DstLineNum > 0) &&
(handle->DstLineNum <= handle->Height)) {
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Pass2],ProgressWnd,NULL,
GTSL_Level,handle->DstLineNum-1,
TAG_END);
HandleProgressIDCMP();
}
handle->Red += (((pic->ilbm->Bmhd.w+15)>>4)<<4);
handle->Green += (((pic->ilbm->Bmhd.w+15)>>4)<<4);
handle->Blue += (((pic->ilbm->Bmhd.w+15)>>4)<<4);
}
}
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Remapping DCTV palette",
TAG_END);
GT_SetGadgetAttrs(ProgressGadgets[GDX_Pass1],ProgressWnd,NULL,
GTSL_Level,2,
TAG_END);
GT_SetGadgetAttrs(ProgressGadgets[GDX_Pass2],ProgressWnd,NULL,
GTSL_Level,0,
TAG_END);
}
// convert to screen palette and then to planar (see above)
xadd = (((pic->ilbm->Bmhd.w+15)>>4)<<4) - pic->ilbm->Bmhd.w;
red = p[0];
blue = p[2];
green = p[1];
if (((struct ExecBase *)SysBase)->AttnFlags & AFF_68020) {
RGBToScreen020(red,green,blue,pic->ilbm->Bmhd.h,pic->ilbm->Bmhd.w,maxcol,xadd,r,g,b);
}
else {
RGBToScreen000(red,green,blue,pic->ilbm->Bmhd.h,pic->ilbm->Bmhd.w,maxcol,xadd,r,g,b);
}
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Converting to Planar",
TAG_END);
HandleProgressIDCMP();
}
if (ChunkyToPlanar(pic,pic->ilbm->Bmhd.w,pic->ilbm->Bmhd.h,p[0])) {
FreeVec(DCTVcolors);
freecolors(pic->ilbm);
FreeArray();
FreeVec(p[0]);
FreeVec(p[1]);
FreeVec(p[2]);
CloseProgressWindow();
FreeDCTVCvt(handle);
return TRUE;
}
else {
e = "Unable to allocate memory for bitmap";
hnum = HE_AllocPlanes;
}
}
else {
e = "Unable to allocate memory for bitmap";
hnum = HE_AllocPlanes;
}
FreeArray();
if (handle) {
FreeDCTVCvt(handle);
}
if (p[0]) FreeVec(p[0]);
if (p[1]) FreeVec(p[1]);
if (p[2]) FreeVec(p[2]);
}
else {
e = "Unable to allocate memory for bitmap";
hnum = HE_AllocPlanes;
}
FreeVec(DCTVcolors);
}
else {
// not 24 bit and not DCTV
// Convert image planar to screen palette planar (using 020+ if present)
if (InitArray(pic->ilbm->Bmhd.w)) {
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Pass2],ProgressWnd,NULL,
GTSL_Max,pic->ilbm->Bmhd.h-1,TAG_END);
HandleProgressIDCMP();
}
InitRastPort(&Rp);
Rp.BitMap = pic->ilbm->brbitmap;
maxcol = min(maxcol,1<<pic->ilbm->Bmhd.nPlanes);
if (((struct ExecBase *)SysBase)->AttnFlags & AFF_68020) {
PaletteToScreen020(&Rp,pic,maxcol,r,g,b);
}
else {
PaletteToScreen000(&Rp,pic,maxcol,r,g,b);
}
// and clean up
FreeArray();
freecolors(pic->ilbm);
CloseProgressWindow();
return TRUE;
}
else {
e = "Unable to allocate memory for bitmap";
hnum = HE_AllocPlanes;
}
}
}
}
}
else {
e = "Unable to AllocIFF";
hnum = HE_AllocIFF;
}
}
// If we are not opening OPAL and the file is not IFF
if ((OpenMode != OPEN_OPAL) &&
(FileFormat != FORMAT_IFF)) {
// if the screen is < 8 colours or we do not allow palette changes or image is not JPEG then
// we will remap later. Otherwise the JPEG code will code will use its own palette
if ((TSMorphWnd->WScreen->BitMap.Depth < 3) || (FileFormat != FORMAT_JPEG) ||
(!PaletteAllowed)) {
ReMap = TRUE;
}
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,
(FileFormat == FORMAT_JPEG)?(ULONG)"Loading JFIF":
(FileFormat == FORMAT_GIF)?(ULONG)"Loading GIF":
(FileFormat == FORMAT_PPM)?(ULONG)"Loading PPM":
(FileFormat == FORMAT_TARGA)?(ULONG)"Loading Targa?":
(ULONG)"Loading ?",
TAG_END);
HandleProgressIDCMP();
}
// try and Load image (JFIF,GIF,PPM,TARGA)
if ((info = LoadJPEG(filename,ReMap?0:min(1<<TSMorphWnd->WScreen->BitMap.Depth,256),r,g,b,&(p[0]))) &&
((info->output_file) || (p[0] && p[1] && p[2]))) {
if (info->output_file) {
p[0] = (UBYTE *)info->output_file;
p[1] = p[0] + (((info->image_width+15)>>4)<<4) * info->image_height;
p[2] = p[1] + (((info->image_width+15)>>4)<<4) * info->image_height;
}
// Allocate BitMap
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Allocating Bitmap",
TAG_END);
HandleProgressIDCMP();
}
pic->ilbm->Bmhd.nPlanes = min(TSMorphWnd->WScreen->BitMap.Depth,8);
pic->ilbm->Bmhd.w = info->image_width;
pic->ilbm->Bmhd.h = info->image_height;
if (InitArray(pic->ilbm->Bmhd.w) && (pic->ilbm->brbitmap = AllocMem(sizeof(struct BitMap),MEMF_CLEAR))) {
InitBitMap(pic->ilbm->brbitmap,pic->ilbm->Bmhd.nPlanes,info->image_width,info->image_height);
for (i=0;
(i < pic->ilbm->Bmhd.nPlanes) && !e; // Allow up to 8 bitplanes
++i) {
if (!(pic->ilbm->brbitmap->Planes[i] = AllocRaster(pic->ilbm->Bmhd.w,pic->ilbm->Bmhd.h))) {
e = "Unable to allocate memory for bitmap";
hnum = HE_AllocPlanes;
}
}
}
else {
e = "Unable to allocate memory for bitmap";
hnum = HE_AllocPlanes;
}
if (!e) {
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Converting to Planar",
TAG_END);
HandleProgressIDCMP();
}
// Remap the RGB image to screen palette if required (see above)
if (ReMap) {
xadd = (((info->image_width+15)>>4)<<4) - info->image_width;
red = p[0];
blue = p[2];
green = p[1];
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Remapping palette",
TAG_END);
GT_SetGadgetAttrs(ProgressGadgets[GDX_Pass2],ProgressWnd,NULL,
GTSL_Level,0,
GTSL_Max,info->image_height-1,TAG_END);
HandleProgressIDCMP();
}
if (((struct ExecBase *)SysBase)->AttnFlags & AFF_68020) {
RGBToScreen020(red,green,blue,info->image_height,info->image_width,maxcol,xadd,r,g,b);
}
else {
RGBToScreen000(red,green,blue,info->image_height,info->image_width,maxcol,xadd,r,g,b);
}
}
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Converting to Planar",
TAG_END);
HandleProgressIDCMP();
}
// Then convert back to planar
if (ChunkyToPlanar(pic,info->image_width,info->image_height,p[0])) {
if (!ReMap) {
// not remapping so reformat JPEGs palette to our format
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Creating Colormap",
TAG_END);
HandleProgressIDCMP();
}
if (pic->ilbm->colortable = (Color4 *)AllocMem(min(1<<TSMorphWnd->WScreen->BitMap.Depth,256)*sizeof(Color4),NULL)) {
pic->ilbm->ncolors = min(1<<TSMorphWnd->WScreen->BitMap.Depth,256);
pic->ilbm->ctabsize = pic->ilbm->ncolors*sizeof(Color4);
for (i = 0;
i < pic->ilbm->ncolors;
++i) {
pic->ilbm->colortable[i] = ((r[i] & 0xf0) << 4) | (g[i] & 0xf0) | (b[i] >> 4);
}
}
}
// Free everything and return OK
FreeArray();
FreeVec(p[0]);
CloseProgressWindow();
return TRUE;
}
else {
e = "Unable to allocate memory for bitmap";
hnum = HE_AllocPlanes;
}
// Free everything
}
FreeArray();
if (pic->ilbm->brbitmap) {
for (i = 0;
(i < pic->ilbm->Bmhd.nPlanes); // Allow up to 8 bitplanes
++i) {
if (!(pic->ilbm->brbitmap->Planes[i])) {
FreeRaster(pic->ilbm->brbitmap->Planes[i],pic->ilbm->Bmhd.w,pic->ilbm->Bmhd.h);
pic->ilbm->brbitmap->Planes[i] = NULL;
}
}
FreeMem(pic->ilbm->brbitmap,sizeof(struct BitMap));
pic->ilbm->brbitmap = NULL;
}
FreeVec(p[0]);
}
}
// If we have not hit a fatal error yet, and opal.library is available then try it
if (!e && OpalBase) {
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Loading using opal.library",
TAG_END);
HandleProgressIDCMP();
}
Err = LoadImage24(NULL,filename,VIRTUALSCREEN24|FORCE24);
if (Err < OL_ERR_MAXERR) {
switch (Err) {
case OL_ERR_OUTOFMEM:
e = "Failure - Out of memory - loading '%s'";
break;
case OL_ERR_OPENFILE:
e = "Failure - Opening file - loading '%s'";
break;
case OL_ERR_FORMATUNKNOWN:
e = "Failure - Unknown Format - loading '%s'";
break;
case OL_ERR_NOTILBM:
e = "Failure - Not an ILBM file - loading '%s'";
break;
case OL_ERR_FILEREAD:
e = "Failure - Reading file - loading '%s'";
break;
case OL_ERR_BADIFF:
e = "Failure - Bad IFF Format - loading '%s'";
break;
case OL_ERR_CANTCLOSE:
e = "Failure - Can not Close - loading '%s'";
break;
case OL_ERR_BADJPEG:
e = "Failure - Bad JPEG Format - loading '%s'";
break;
case OL_ERR_UNSUPPORTED:
e = "Failure - Unsupported Format - loading '%s'";
break;
case OL_ERR_CTRLC:
case OL_ERR_NOTHUMBNAIL:
case OL_ERR_OPENSCREEN:
case OL_ERR_FILEWRITE:
default:
e = "Failure - Unknown problem - loading '%s'";
break;
}
e1 = filename;
hnum = HE_OpalVision;
}
else {
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Converting to RGB",
TAG_END);
HandleProgressIDCMP();
}
OScrn = (struct OpalScreen *)Err;
// Allocate chunky bit maps
if ((p[0] = AllocVec(((((OScrn->Width+15)>>4)<<4)*OScrn->Height),0)) &&
(p[1] = AllocVec(((((OScrn->Width+15)>>4)<<4)*OScrn->Height),0)) &&
(p[2] = AllocVec(((((OScrn->Width+15)>>4)<<4)*OScrn->Height),0))) {
// Convert Opal vision screen to RGB
OVtoRGB(OScrn,p,0,0,((OScrn->Width+15)>>4)<<4,OScrn->Height);
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Allocating Bitmap",
TAG_END);
HandleProgressIDCMP();
}
pic->ilbm->Bmhd.nPlanes = min(TSMorphWnd->WScreen->BitMap.Depth,8);
pic->ilbm->Bmhd.w = OScrn->Width;
pic->ilbm->Bmhd.h = OScrn->Height;
// Allocate BitMap
if (InitArray(pic->ilbm->Bmhd.w) && (pic->ilbm->brbitmap = AllocMem(sizeof(struct BitMap),MEMF_CLEAR))) {
InitBitMap(pic->ilbm->brbitmap,pic->ilbm->Bmhd.nPlanes,OScrn->Width,OScrn->Height);
for (i=0;
(i < pic->ilbm->Bmhd.nPlanes) && !e; // Allow up to 8 bitplanes
++i) {
if (!(pic->ilbm->brbitmap->Planes[i] = AllocRaster(pic->ilbm->Bmhd.w,pic->ilbm->Bmhd.h))) {
e = "Unable to allocate memory for bitmap";
hnum = HE_AllocPlanes;
}
}
}
else {
e = "Unable to allocate memory for bitmap";
hnum = HE_AllocPlanes;
}
// remap to screen palette and convert to planar - see above
if (!e) {
xadd = (((OScrn->Width+15)>>4)<<4) - OScrn->Width;
red = p[0];
blue = p[2];
green = p[1];
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Remapping OPAL palette",
TAG_END);
GT_SetGadgetAttrs(ProgressGadgets[GDX_Pass2],ProgressWnd,NULL,
GTSL_Level,0,
GTSL_Max,OScrn->Height-1,TAG_END);
HandleProgressIDCMP();
}
if (((struct ExecBase *)SysBase)->AttnFlags & AFF_68020) {
RGBToScreen020(red,green,blue,OScrn->Height,OScrn->Width,maxcol,xadd,r,g,b);
}
else {
RGBToScreen000(red,green,blue,OScrn->Height,OScrn->Width,maxcol,xadd,r,g,b);
}
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Converting to Planar",
TAG_END);
HandleProgressIDCMP();
}
if (!ChunkyToPlanar(pic,OScrn->Width,OScrn->Height,p[0])) {
e = "Unable to allocate memory for bitmap";
hnum = HE_AllocPlanes;
}
// Free everything and return
}
else {
if (pic->ilbm->brbitmap) {
for (i = 0;
(i < pic->ilbm->Bmhd.nPlanes); // Allow up to 8 bitplanes
++i) {
if (!(pic->ilbm->brbitmap->Planes[i])) {
FreeRaster(pic->ilbm->brbitmap->Planes[i],pic->ilbm->Bmhd.w,pic->ilbm->Bmhd.h);
pic->ilbm->brbitmap->Planes[i] = NULL;
}
}
FreeMem(pic->ilbm->brbitmap,sizeof(struct BitMap));
pic->ilbm->brbitmap = NULL;
}
}
FreeArray();
}
else {
e = "Unable to allocate memory for bitmap";
hnum = HE_AllocPlanes;
}
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Cleaning up",
TAG_END);
HandleProgressIDCMP();
}
if (p[0]) FreeVec(p[0]);
if (p[1]) FreeVec(p[1]);
if (p[2]) FreeVec(p[2]);
FreeScreen24(OScrn);
if (!e) {
pic->Opal = TRUE;
CloseProgressWindow();
return TRUE;
}
}
}
else {
if (!e) {
e = "No opal.library";
hnum = HE_NoOpal;
}
}
// display error and return
Error(e,"OK",e1,hnum);
CloseProgressWindow();
return FALSE;
}
extern struct RastPort RP={0}, // Work Rast Ports
TRP={0};
extern struct BitMap TBM={0}; // Temp bitmap
extern UBYTE *plane0=NULL; // Planes for temporary bit maps
extern UBYTE *plane1=NULL;
extern UBYTE *plane2=NULL;
extern UBYTE *plane3=NULL;
extern UBYTE *plane4=NULL;
extern UBYTE *plane5=NULL;
extern UBYTE *plane6=NULL;
extern UBYTE *plane7=NULL;
extern UBYTE *Array=NULL;
/* Allocate and initialise things for image conversion
* w : width of image
*/
BOOL
InitArray(UWORD w) {
if ((plane0 = AllocVec((((w+15)>>4)<<4),MEMF_CHIP)) &&
(plane1 = AllocVec((((w+15)>>4)<<4),MEMF_CHIP)) &&
(plane2 = AllocVec((((w+15)>>4)<<4),MEMF_CHIP)) &&
(plane3 = AllocVec((((w+15)>>4)<<4),MEMF_CHIP)) &&
(plane4 = AllocVec((((w+15)>>4)<<4),MEMF_CHIP)) &&
(plane5 = AllocVec((((w+15)>>4)<<4),MEMF_CHIP)) &&
(plane6 = AllocVec((((w+15)>>4)<<4),MEMF_CHIP)) &&
(plane7 = AllocVec((((w+15)>>4)<<4),MEMF_CHIP)) &&
(Array = AllocVec((((w+15)>>4)<<4),MEMF_CLEAR))) {
InitRastPort(&RP);
InitRastPort(&TRP);
InitBitMap(&TBM,8,w,1);
TRP.BitMap = &TBM;
TBM.Planes[0]=plane0;
TBM.Planes[1]=plane1;
TBM.Planes[2]=plane2;
TBM.Planes[3]=plane3;
TBM.Planes[4]=plane4;
TBM.Planes[5]=plane5;
TBM.Planes[6]=plane6;
TBM.Planes[7]=plane7;
return TRUE;
}
FreeArray();
return FALSE;
}
/* Free everything allocated
* by InitArray()
*/
void
FreeArray(void) {
if (plane0) {
FreeVec(plane0);
plane0 = NULL;
}
if (plane1) {
FreeVec(plane1);
plane1 = NULL;
}
if (plane2) {
FreeVec(plane2);
plane2 = NULL;
}
if (plane3) {
FreeVec(plane3);
plane3 = NULL;
}
if (plane4) {
FreeVec(plane4);
plane4 = NULL;
}
if (plane5) {
FreeVec(plane5);
plane5 = NULL;
}
if (plane6) {
FreeVec(plane6);
plane6 = NULL;
}
if (plane7) {
FreeVec(plane7);
plane7 = NULL;
}
if (Array) {
FreeVec(Array);
Array = NULL;
}
}
/* Convert Chunky 8 bit to planar
* Always return true (historical)
* pic - picture pointer
* w - width
* h - height
* chunky - chunky plane
*/
BOOL
ChunkyToPlanar(struct Picture *pic,UWORD w,UWORD h,UBYTE *chunky) {
RP.BitMap = pic->ilbm->brbitmap;
WritePixelArray8(&RP,0,0,w-1,h-1,chunky,&TRP);
return TRUE;
}
/* Convert 24 bit chunky to RGB planar
* Always return true (historical)
* pic - picture pointer
* w - width
* h - height
* r,g,b - chunky pointers
*/
BOOL
PlanarToChunky(struct Picture *pic,UWORD w,UWORD h,UBYTE *r,UBYTE *g,UBYTE *b) {
struct BitMap BM;
InitBitMap(&BM,8,w,h);
RP.BitMap = &BM;
BM.Planes[0] = pic->ilbm->brbitmap->Planes[0];
BM.Planes[1] = pic->ilbm->brbitmap->Planes[1];
BM.Planes[2] = pic->ilbm->brbitmap->Planes[2];
BM.Planes[3] = pic->ilbm->brbitmap->Planes[3];
BM.Planes[4] = pic->ilbm->brbitmap->Planes[4];
BM.Planes[5] = pic->ilbm->brbitmap->Planes[5];
BM.Planes[6] = pic->ilbm->brbitmap->Planes[6];
BM.Planes[7] = pic->ilbm->brbitmap->Planes[7];
// Convert red to chunky
ReadPixelArray8(&RP,0,0,w-1,h-1,r,&TRP);
WaitBlit();
BM.Planes[0] = pic->ilbm->brbitmap->Planes[8];
BM.Planes[1] = pic->ilbm->brbitmap->Planes[9];
BM.Planes[2] = pic->ilbm->brbitmap->Planes[10];
BM.Planes[3] = pic->ilbm->brbitmap->Planes[11];
BM.Planes[4] = pic->ilbm->brbitmap->Planes[12];
BM.Planes[5] = pic->ilbm->brbitmap->Planes[13];
BM.Planes[6] = pic->ilbm->brbitmap->Planes[14];
BM.Planes[7] = pic->ilbm->brbitmap->Planes[15];
// and green
ReadPixelArray8(&RP,0,0,w-1,h-1,g,&TRP);
WaitBlit();
BM.Planes[0] = pic->ilbm->brbitmap->Planes[16];
BM.Planes[1] = pic->ilbm->brbitmap->Planes[17];
BM.Planes[2] = pic->ilbm->brbitmap->Planes[18];
BM.Planes[3] = pic->ilbm->brbitmap->Planes[19];
BM.Planes[4] = pic->ilbm->brbitmap->Planes[20];
BM.Planes[5] = pic->ilbm->brbitmap->Planes[21];
BM.Planes[6] = pic->ilbm->brbitmap->Planes[22];
BM.Planes[7] = pic->ilbm->brbitmap->Planes[23];
// and blue
ReadPixelArray8(&RP,0,0,w-1,h-1,b,&TRP);
WaitBlit();
return TRUE;
}
/* RGB to screen palette
* 68000/010 version
* red,green,blue : chunky pointers - result is pallete mapped chunky in red
* Height,Width : image size
* maxcol : number of colours
* xadd : skip at end of line
* r,g,b : r,g,b palette
*/
void
RGBToScreen000(UBYTE *red,UBYTE *green,UBYTE *blue,UWORD Height,UWORD Width,
UWORD maxcol,UWORD xadd,UBYTE *r,UBYTE *g,UBYTE *b) {
UWORD i,j,k;
ULONG maxdiff;
ULONG diff;
LONG t;
UWORD index;
// for each line
for (j = 0;
j < Height;
++j) {
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Pass2],ProgressWnd,NULL,
GTSL_Level,(ULONG)j,TAG_END);
HandleProgressIDCMP();
}
// for each pixel
for (i = 0;
i < Width;
++i) {
// Find closest color based on:
// red_difference*sqrt(3)+green_difference*srqt(6)+blue_difference
// (some sort of logic in the figures somewhere)
maxdiff = 0x7FFFFFFF;
for (k = 0;
k < maxcol;
++k) {
t = *red - r[k];
diff = t*t*3;
t = *green - g[k];
diff += (t*t*6);
t = *blue - b[k];
diff += (t*t);
if (diff < maxdiff) {
maxdiff = diff;
index = k;
}
}
// Store index to color
*red = index;
++red;
++green;
++blue;
}
red += xadd;
green += xadd;
blue += xadd;
if (ProgressWnd) {
HandleProgressIDCMP();
}
}
}
/* Palette to screen palette
* 68000/010 version
* Rp : work rast port
* pic : picture pointer
* maxcol: number of colours
* r,g,b : r,g,b palette
*/
void
PaletteToScreen000(struct RastPort *Rp,struct Picture *pic,UWORD maxcol,
UBYTE *r,UBYTE *g,UBYTE *b) {
UWORD i,j,k; // loop counters
LONG penno;
UBYTE rr,gg,bb;
ULONG maxdiff;
ULONG diff;
UWORD index;
LONG t; // temp diff
UWORD EHB;
BOOL isHAM6 = FALSE;
BOOL isHAM8 = FALSE;
BOOL isEHB = FALSE;
struct DisplayInfo queryinfo;
DisplayInfoHandle handle;
struct BitMap BM;
UBYTE *arrayp;
// Initialise stuff
InitBitMap(&BM,pic->ilbm->Bmhd.nPlanes,pic->ilbm->Bmhd.w,pic->ilbm->Bmhd.h);
RP.BitMap = &BM;
InitBitMap(&TBM,pic->ilbm->Bmhd.nPlanes,pic->ilbm->Bmhd.w,1);
TRP.BitMap = &TBM;
TBM.Planes[0]=plane0;
TBM.Planes[1]=plane1;
TBM.Planes[2]=plane2;
TBM.Planes[3]=plane3;
TBM.Planes[4]=plane4;
TBM.Planes[5]=plane5;
TBM.Planes[6]=plane6;
TBM.Planes[7]=plane7;
// based on CAMG chunk determine special type of image
if ((handle = FindDisplayInfo(pic->ilbm->camg)) &&
(GetDisplayInfoData(handle,(UBYTE *)&queryinfo,sizeof(queryinfo),DTAG_DISP,NULL))) {
// 6 plane HAM
if ((pic->ilbm->Bmhd.nPlanes == 6) && (queryinfo.PropertyFlags & DIPF_IS_HAM)) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Remapping HAM6 palette",
TAG_END);
isHAM6 = TRUE;
}
else {
// 8 plane HAM
if ((pic->ilbm->Bmhd.nPlanes == 8) && (queryinfo.PropertyFlags & DIPF_IS_HAM)) {
isHAM8 = TRUE;
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Remapping HAM8 palette",
TAG_END);
}
else {
// 6 plane EHB
if ((pic->ilbm->Bmhd.nPlanes == 6) && (queryinfo.PropertyFlags & DIPF_IS_EXTRAHALFBRITE)) {
isEHB = TRUE;
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Remapping EHB palette",
TAG_END);
}
else {
// standard ILBM
GT_SetGadgetAttrs(ProgressGadgets[GDX_Mess],ProgressWnd,NULL,
GTTX_Text,(ULONG)"Remapping ILBM palette",
TAG_END);
}
}
}
}
// for each line
for (j = 0;
j < pic->ilbm->Bmhd.h;
++j) {
if (ProgressWnd) {
GT_SetGadgetAttrs(ProgressGadgets[GDX_Pass2],ProgressWnd,NULL,
GTSL_Level,(ULONG)j,TAG_END);
HandleProgressIDCMP();
}
// convert line to chunky
ReadPixelLine8(Rp,0,j,pic->ilbm->Bmhd.w,Array,&TRP);
arrayp = Array;
// for each pixel depending on mode convert line to screen palette (like palette to screen)
if (isHAM6) {
// rgb = 0 at start of line
rr = gg = bb = 0;
for (i = 0;
i < pic->ilbm->Bmhd.w;
++i) {
penno = *arrayp;
switch (penno & 0x30) { // HAM selection
case 0:
rr = pic->ilbm->RGB[penno*4+1];
gg = pic->ilbm->RGB[penno*4+2];
bb = pic->ilbm->RGB[penno*4+3];
break;
case 0x10:
bb = (penno&0xf)|((penno&0xf)<<4);
break;
case 0x20:
rr = (penno&0xf)|((penno&0xf)<<4);
break;
case 0x30:
gg = (penno&0xf)|((penno&0xf)<<4);
break;
}
// Find closest color
maxdiff = 0x7FFFFFFF;
for (k = 0;
k < maxcol;
++k) {
t = rr - r[k];
diff = t*t*3;
t = gg - g[k];
diff += (t*t*6);
t = bb - b[k];
diff += (t*t);
if (diff < maxdiff) {
maxdiff = diff;
index = k;
}
}
*arrayp++ = index;
}
}
else {
if (isHAM8) {
// very similar to HAM6
rr = gg = bb = 0;
for (i = 0;
i < pic->ilbm->Bmhd.w;
++i) {
penno = *arrayp;
switch (penno & 0xc0) {
case 0:
rr = pic->ilbm->RGB[penno*4+1];
gg = pic->ilbm->RGB[penno*4+2];
bb = pic->ilbm->RGB[penno*4+3];
break;
case 0x40:
bb = (penno&0x3f)<<2;
break;
case 0x80:
rr = (penno&0x3f)<<2;
break;
case 0xc0:
gg = (penno&0x3f)<<2;
break;
}
// Find closest color
maxdiff = 0x7FFFFFFF;
for (k = 0;
k < maxcol;
++k) {
t = rr - r[k];
diff = t*t*3;
t = gg - g[k];
diff += (t*t*6);
t = bb - b[k];
diff += (t*t);
if (diff < maxdiff) {
maxdiff = diff;
index = k;
}
}
*arrayp++ = index;
}
}
else {
if (isEHB) {
// simple - just check highest plane and divide by two if required
for (i = 0;
i < pic->ilbm->Bmhd.w;
++i) {
penno = *arrayp;
EHB = (penno & 0x20)?1:0;
penno &= 0x1f;
rr = pic->ilbm->RGB[penno*4+1]>>EHB;
gg = pic->ilbm->RGB[penno*4+2]>>EHB;
bb = pic->ilbm->RGB[penno*4+3]>>EHB;
// Find closest color
maxdiff = 0x7FFFFFFF;
for (k = 0;
k < maxcol;
++k) {
t = rr - r[k];
diff = t*t*3;
t = gg - g[k];
diff += (t*t*6);
t = bb - b[k];
diff += (t*t);
if (diff < maxdiff) {
maxdiff = diff;
index = k;
}
}
*arrayp++ = index;
}
}
else {
// simple palette remap
for (i = 0;
i < pic->ilbm->Bmhd.w;
++i) {
penno = *arrayp;
rr = pic->ilbm->RGB[penno*4+1];
gg = pic->ilbm->RGB[penno*4+2];
bb = pic->ilbm->RGB[penno*4+3];
// Find closest color
maxdiff = 0x7FFFFFFF;
for (k = 0;
k < maxcol;
++k) {
t = rr - r[k];
diff = t*t*3;
t = gg - g[k];
diff += (t*t*6);
t = bb - b[k];
diff += (t*t);
if (diff < maxdiff) {
maxdiff = diff;
index = k;
}
}
*arrayp++ = index;
}
}
}
}
// Convert line from chunky palette to planar
WritePixelLine8(Rp,0,j,pic->ilbm->Bmhd.w,Array,&TRP);
}
}